package com.yjhh.chdataservice.component;

import com.yjhh.chdataservice.InitDataFactory;
import com.yjhh.chdataservice.beans.CommonNameValueVo;
import com.yjhh.chdataservice.beans.DeptBean;
import com.yjhh.chdataservice.beans.MaxYearMonth;
import com.yjhh.chdataservice.except.YJHHException;
import com.yjhh.chdataservice.util.DataTools;
import com.yjhh.chdataservice.util.XaUtil;
import lombok.extern.log4j.Log4j;
import lombok.extern.log4j.Log4j2;
import net.sf.json.JSONObject;
import org.apache.avro.generic.GenericData;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.max.InternalMax;
import org.elasticsearch.search.aggregations.metrics.max.MaxAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * Created by hlantian on 2017/10/20.
 * 公共数据管理
 */
@Component
@Log4j2
public class CommonDataComponent {

    @Autowired
    private ESClientManager esClientManager;

    @Autowired
    private InitDataFactory initDataFactory;

    /**
     * 根据区域编码获取部门信息
     *
     * @param areacode
     * @return
     * @throws YJHHException
     */
    public DeptBean getSysDeptInfo(String areacode) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("areacode", areacode));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient()
                .prepareSearch("sy_dept_info")
                .setTypes("sy_dept")
                .setSize(10)
                .setQuery(areacodequery);
        SearchResponse searchResponse = null;
        log.info("reqeust: " + searchRequestBuilder.toString());
        searchResponse = searchRequestBuilder.execute().actionGet();
        DeptBean deptBean = new DeptBean();
        if (searchResponse.getHits().getTotalHits() > 0) {
            SearchHit at = searchResponse.getHits().getAt(0);
            Object deptleveObj = at.getSource().get("deptlevel");
            if(deptleveObj != null){
                deptBean.setDeptLevel(Integer.parseInt(deptleveObj.toString()));
            }
            deptBean.setDeptID(at.getId());
            deptBean.setAreaCode(areacode);
            deptBean.setDeptno(at.getSource().get("deptno").toString());
            deptBean.setDeptName(at.getSource().get("deptname").toString());
            if (deptBean.getDeptLevel() != 1 && at.getSource().get("areatype") != null) {
                deptBean.setAreaType(at.getSource().get("areatype").toString());
            }
        } else {
            throw new YJHHException("No Dept Data Find");
        }
        return deptBean;
    }


    /**
     * 根据片区获取区域信息
     *
     * @param area
     * @return
     * @throws YJHHException
     */
    public List<DeptBean> getSysDeptInfo(String area, String deptlevel) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("areatype.keyword", area));
        if (!XaUtil.isEmpty(deptlevel)) {
            areacodequery.must(termQuery("deptlevel", deptlevel));
        }
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient()
                .prepareSearch("sy_dept_info")
                .setTypes("sy_dept")
                .setSize(100)
                .setQuery(areacodequery);
        SearchResponse searchResponse = null;
        log.info("reqeust: " + searchRequestBuilder.toString());
        searchResponse = searchRequestBuilder.execute().actionGet();
        List<DeptBean> deptBeans = new ArrayList<>();
        if (searchResponse.getHits().getTotalHits() > 0) {
            for (SearchHit at : searchResponse.getHits()) {
                DeptBean deptBean = new DeptBean();
                deptBean.setDeptLevel(Integer.parseInt(at.getSource().get("deptlevel").toString()));
                deptBean.setDeptID(at.getId());
                deptBean.setAreaCode(at.getSource().get("areacode").toString());
                deptBean.setDeptno(at.getSource().get("deptno").toString());
                deptBean.setDeptName(at.getSource().get("deptname").toString());
                deptBean.setAreaLevel(at.getSource().get("arealevel").toString());
                deptBean.setAreaType(at.getSource().get("areatype").toString());
                deptBeans.add(deptBean);
            }
        } else {
            throw new YJHHException("No Dept Data Find");
        }
        return deptBeans;
    }

    /**
     * 字典编码转化为字典名
     *
     * @param id
     * @return
     */
    public String getSysDicValueById(String id) {
        Map<String, Map<String, Object>> sysDicMap = initDataFactory.getSysDicMap();
        if (sysDicMap == null || StringUtils.isBlank(id)) {
            return id;
        }
        List<String> dicNameBuf = new ArrayList<>();
        if (id.contains(",")) {
            String[] ids = id.split(",");
            for (String idStr : ids) {
                if (sysDicMap.containsKey(idStr)) {
                    Object dictname = sysDicMap.get(idStr).get("dictname");
                    dicNameBuf.add(dictname == null ? id : dictname.toString());
                }
            }
        } else {
            if (sysDicMap.containsKey(id)) {
                Object dictname = sysDicMap.get(id).get("dictname");
                dicNameBuf.add(dictname == null ? id : dictname.toString());
            }
        }
        return StringUtils.join(dicNameBuf, " ");
    }

    public List<String> getSysDicValueListById(String id) {
        List<String> dicNameBuf = new ArrayList<>();
        Map<String, Map<String, Object>> sysDicMap = initDataFactory.getSysDicMap();
        if (sysDicMap == null || StringUtils.isBlank(id)) {
            return dicNameBuf;
        }
        if (id.contains(",")) {
            String[] ids = id.split(",");
            for (String idStr : ids) {
                if (sysDicMap.containsKey(idStr)) {
                    Object dictname = sysDicMap.get(idStr).get("dictname");
                    dicNameBuf.add(dictname == null ? id : dictname.toString());
                }
            }
        } else {
            if (sysDicMap.containsKey(id)) {
                Object dictname = sysDicMap.get(id).get("dictname");
                dicNameBuf.add(dictname == null ? id : dictname.toString());
            }
        }
        return dicNameBuf;
    }

    /**
     * 根据数据字典PID获取子数据字典
     * @param pid
     * @return
     */
    public List<String> getSubDicValuesByPId(String pid) {
        Map<String, Map<String, Object>> sysDicMap = initDataFactory.getSysDicMap();
        if (sysDicMap == null || StringUtils.isBlank(pid)) {
            return null;
        }
        List<String> subDictNameList = sysDicMap.values().parallelStream()
                .filter(dict -> dict.get("dictpid") != null && pid.equalsIgnoreCase(dict.get("dictpid").toString()))
                .map(dict -> (String)dict.get("dictname"))
                .collect(Collectors.toList());

        return subDictNameList;
    }

    /**
     * 获取子部门
     *
     * @param deptId
     * @return
     */
    public List<DeptBean> getSubDeptByDeptId(String deptId) {

        List<DeptBean> deptBeanList = new ArrayList<>();
        Map<String, JSONObject> deptInfoMap = initDataFactory.getDeptInfoMap();
        Collection<JSONObject> values = deptInfoMap.values();
        for (JSONObject jsonObject : values) {
            if (jsonObject.containsKey("deptid") && jsonObject.containsKey("deptpid") && StringUtils.equalsIgnoreCase(jsonObject.getString("deptpid"), deptId)) {
                DeptBean deptBean = new DeptBean();
                deptBean.setDeptLevel(Integer.parseInt(jsonObject.getString("deptlevel")));
                deptBean.setDeptID(jsonObject.getString("deptid"));
                deptBean.setDeptno(jsonObject.getString("deptno"));
                deptBean.setDeptName(jsonObject.getString("deptname"));
                deptBean.setAreaLevel(jsonObject.getString("arealevel"));
                deptBean.setAreaCode(jsonObject.getString("areacode"));
                deptBean.setAreaType(jsonObject.getString("areatype"));
                deptBeanList.add(deptBean);
            }
        }

        //对结果进行排序
        Collections.sort(deptBeanList, (DeptBean o1, DeptBean o2) -> {
            String areaCode2 = o2.getAreaCode();
            String areaCode1 = o1.getAreaCode();

            //为空则不比较
            if(StringUtils.isBlank(areaCode1) || StringUtils.isBlank(areaCode2)){
                return 1;
            }

            return Long.parseLong(areaCode2) >= Long.parseLong(areaCode1) ? -1 : 1;
        });

        return deptBeanList;
    }

    public DeptBean getDeptByDeptName(String deptName) {

        Map<String, JSONObject> deptInfoMap = initDataFactory.getDeptInfoMap();
        Collection<JSONObject> values = deptInfoMap.values();
        for (JSONObject jsonObject : values) {
            if (jsonObject.containsKey("deptname")  && StringUtils.equalsIgnoreCase(jsonObject.getString("deptname"), deptName)) {
                DeptBean deptBean = new DeptBean();
                deptBean.setDeptLevel(Integer.parseInt(jsonObject.getString("deptlevel")));
                deptBean.setDeptID(jsonObject.getString("deptid"));
                deptBean.setDeptno(jsonObject.getString("deptno"));
                deptBean.setDeptName(jsonObject.getString("deptname"));
                deptBean.setAreaLevel(jsonObject.getString("arealevel"));
                deptBean.setAreaCode(jsonObject.getString("areacode"));
                deptBean.setAreaType(jsonObject.getString("areatype"));
                return deptBean;
            }
        }

        return null;
    }

    public MaxYearMonth getMaxReportYearMonth(String yearCond) {
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("pl_imppr_targetdata").setTypes("imppr_targetdata")
                .setSize(0);

        if(yearCond == null || StringUtils.isBlank(yearCond)){
            searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
        }else{
            searchRequestBuilder.setQuery(QueryBuilders.termQuery("fillyear",yearCond));
        }

        TermsAggregationBuilder yearAgg = AggregationBuilders.terms("aggYear").field("fillyear").size(1);
        yearAgg.order(Terms.Order.term(false));
        yearAgg.size(1);

        MaxAggregationBuilder maxAggregationBuilder = AggregationBuilders.max("maxMonth").field("fillmonth");
        yearAgg.subAggregation(maxAggregationBuilder);

        searchRequestBuilder.addAggregation(yearAgg);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        Aggregations aggregations = searchResponse.getAggregations();
        List<Aggregation> aggregationsList = aggregations.asList();
        if (aggregationsList == null || aggregationsList.size() <= 0) {
            return null;
        }
        LongTerms longTerms = (LongTerms) aggregationsList.get(0);
        List<LongTerms.Bucket> buckets = longTerms.getBuckets();
        if (buckets == null || buckets.size() <= 0) {
            return null;
        }
        LongTerms.Bucket bucket = buckets.get(0);

        String maxYear = bucket.getKeyAsString();
        List<Aggregation> monthAggregations = bucket.getAggregations().asList();
        InternalMax monthInternalMax = (InternalMax) monthAggregations.get(0);
        String maxMonth = monthInternalMax.getValueAsString();

        return new MaxYearMonth(maxYear, maxMonth);
    }

    /**
     * 根据部门ID获取部门对象
     *
     * @param deptId 部门ID
     * @return
     */
    public DeptBean getDeptByDeptId(String deptId) {
        Map<String, JSONObject> deptInfoMap = initDataFactory.getDeptInfoMap();
        if (!deptInfoMap.containsKey(deptId)) {
            return null;
        }
        JSONObject jsonObject = deptInfoMap.get(deptId);
        DeptBean deptBean = new DeptBean();
        deptBean.setDeptLevel(Integer.parseInt(jsonObject.getString("deptlevel")));
        deptBean.setDeptID(jsonObject.getString("deptid"));
        deptBean.setDeptno(jsonObject.getString("deptno"));
        deptBean.setDeptName(jsonObject.getString("deptname"));
        deptBean.setAreaLevel(jsonObject.getString("arealevel"));
        deptBean.setAreaCode(jsonObject.getString("areacode"));
        deptBean.setAreaType(jsonObject.getString("areatype"));
        String longitude = jsonObject.getString
                ("longitude");
        deptBean.setX(StringUtils.isBlank(DataTools.convertToStr(longitude)) || !DataTools.isDouble(longitude) ? 0.0 : Double
                .parseDouble
                        (DataTools.convertToStr(longitude)));
        String latitude = jsonObject.getString
                ("latitude");
        deptBean.setY(StringUtils.isBlank(DataTools.convertToStr(latitude)) || !DataTools.isDouble(latitude) ? 0.0 : Double
                .parseDouble
                        (DataTools.convertToStr(latitude)));

        return deptBean;
    }

}
